package com.guochenglang.www.util;

import com.guochenglang.www.service.section.LogHandlerSection;
import com.guochenglang.www.util.error.MyExceptionHandler;

import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedHashMap;
import java.util.Properties;

/**
 * 通过properties实现注入依赖
 *
 * @author 23217
 */
public class MyDependency {
    private static final MyDependency MY_DEPENDENCY = new MyDependency();
    /**
     * Class是接口，Object是实现类，注入的实现类集合
     */
    private static final LinkedHashMap<Class<?>, Object> BEAN = new LinkedHashMap<>();

    /**
     * 对外提供实现的对象
     *
     * @param interfaceClass 接口字节码文件
     * @param <T>            泛型返回值
     * @return 泛型结果
     */
    public static <T> T returnObject(Class<T> interfaceClass) {
        //若已经注入过，则直接获得实现类
        if (!BEAN.isEmpty() && BEAN.containsKey(interfaceClass)) {
            return (T) BEAN.get(interfaceClass);
        }
        //为注入过
        //调用方法获得实例名
        String className = getClassName(interfaceClass.getName());
        if (className != null) {
            //实现接口，并存到BEAN中
            T value = (T) MY_DEPENDENCY.getLibInstance(className);
            BEAN.put(interfaceClass, value);
            return value;
        } else {
            T value = (T) MY_DEPENDENCY.getLibInstance(interfaceClass.getName());
            BEAN.put(interfaceClass, value);
            return value;
        }

    }

    private MyDependency() {
    }

    /**
     * 获得代理对象
     *
     * @param className 实现类名字
     * @return 实现类对象
     */
    private Object getLibInstance(String className) {
        LogHandlerSection logHandlerSection = new LogHandlerSection();
        try {
            Class<?> aClass = Class.forName(className);
            return logHandlerSection.getProxy(aClass);
        } catch (ClassNotFoundException e) {
            MyExceptionHandler.registerHandler();
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取实现类类名方法
     *
     * @param interfaceName 接口名
     * @return 返回实现类类名
     */
    private static String getClassName(String interfaceName) {
        //读取properties文件，获取实例名
        Properties prop = new Properties();
        InputStream resourceAsStream = MyDependency.class.getClassLoader().getResourceAsStream("Dependency.properties");
        try {
            prop.load(resourceAsStream);
            String simpleClassName = getSimpleClassName(interfaceName);
            //若已写入properties，返回实例名
            if (prop.containsKey(simpleClassName)) {
                return getImplName(interfaceName);
            } else {
                return null;
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获得接口名
     *
     * @param className 接口的全类名
     * @return 接口的名字
     */
    private static String getSimpleClassName(String className) {
        return className.substring(className.lastIndexOf(".") + 1);
    }

    /**
     * 获得实现类的全类名
     *
     * @param interfaceName 接口全类名
     * @return 实现类的全类名
     */
    private static String getImplName(String interfaceName) {
        int index = interfaceName.lastIndexOf(".");
        String simpleName = interfaceName.substring(index + 1);
        return interfaceName.substring(0, index) + ".impl." + simpleName + "Impl";
    }

}
